{
    class TileMap extends Laya.Box {
        constructor () {
            super();
            
            this.bg = null;
            this.floorLayer = null;
            this.buildingLayer = null;
            this.data = Laya.loader.getRes("assets/map/map.json");

            this.mapWidth = 0;
            this.mapHeight = 0;
            this.row = 0;
            this.col = 0;
            this.floors = [];
            this.buildings = [];
            // this.roles = {};
            // this.bullets = {};

            this.eventActions = null;

            this.init();
        }

        destroy () {
            super.destroy();
            Sail.io.unregister(this.eventActions);
        }

        init () {
            this.row = this.data.meta.size.h;
            this.col = this.data.meta.size.w;

            this.mapHeight = this.row * this.data.meta.tilesize.h;
            this.mapWidth = this.col * this.data.meta.tilesize.w;

            Com.Room.Map.TileTexture.setup(this.data);
            let bg = new Laya.Image("assets/map/bg.jpg");
                bg.centerX = 0;
                bg.centerY = 0;

            this.size(bg.width * 2, bg.height * 2);
            bg.scale(2, 2);

            let floorLayer = new Laya.Box();
                floorLayer.size(this.mapWidth, this.mapHeight);
                floorLayer.centerX = 0;
                floorLayer.centerY = 0;

            let buildingLayer = new Laya.Box();
                buildingLayer.size(this.mapWidth, this.mapHeight);
                buildingLayer.centerX = 0;
                buildingLayer.centerY = 0;

            this.bg = bg;
            this.floorLayer = floorLayer;
            this.buildingLayer = buildingLayer;
            this.addChildren(bg, floorLayer, buildingLayer);

            this.addTiles(this.data.positions, this.data.frames);

            this.eventActions = {
                "role.move" : this.scrollViewPort,

                "map.add" : this.addItem,

                // "map.add.bullet" : this.addBullet,
                // "map.remove.bullet" : this.removeBullet,

                "map.action" : this.actions,
                "map.event" : this.events
            };
            Sail.io.register(this.eventActions, this);
        }

        addTiles (pos, frames){
            for(let i in pos){
                let _data = pos[i];
                let layer = this[`${i}Layer`];
                let wrap = this[`${i}s`];
                for(let j in _data){
                    let tileData = _data[j];
                    let tileFramesData = frames[j];
                    for(let k = 0; k < tileData.length; k++){
                        let tile = Com.Room.Map.TileTexture.create(j, tileData[k], tileFramesData);
                        wrap[tile.itemid] = tile;
                        layer.addChild(tile);
                    }
                }
            }
        }

        addItem (item) {
            this.buildingLayer.addChild(item);
        }

        // addBullet (bullet) {
        //     this.bullets[bullet.bulletId] = bullet;
        //     this.buildingLayer.addChild(bullet);
        // }

        // removeBullet (bid) {
        //     this.bullets[bid].recover();
        //     delete this.bullets[bid];
        // }

        addSellCase(shellCase){
            this.buildingLayer.addChild(shellCase);
        }

        scrollViewPort (data) {
            if(data.x > Laya.stage.width / 2 - 250){
                this.x = -(data.x - Laya.stage.width / 2 + 250);
                // console.log(this.x, -(this.width - Laya.stage.width), this.x < -(this.width - Laya.stage.width))
                if(this.x < -(this.width - Laya.stage.width)){
                    this.x = -(this.width - Laya.stage.width);
                }
            }else{
                this.x = 0;
            }
            if(data.y > Laya.stage.height / 2 - 250){
                this.y = -(data.y - Laya.stage.height / 2 + 250);
                // console.log(this.x, -(this.width - Laya.stage.width), this.x < -(this.width - Laya.stage.width))
                if(this.y < -(this.height - Laya.stage.height)){
                    this.y = -(this.height - Laya.stage.height);
                }
            }else{
                this.y = 0;
            }
        }

        loopShake () {
            this.curTimes++;
            
            if(this.curTimes >= this.totalTimes){
                this.reset();
                return;
            }

            this.x = 3 * (Math.random() > 0.5 ? 1 : -1);
            this.y = 3 * (Math.random() > 0.5 ? 1 : -1);
        }

        /**
         * 地图抖动效果
         * @param {Number} level 抖动级别，普通攻击：1，终结技：5
         * @param {Number} times 抖动次数
         */
        shake (level, times) {
            if(!times){
                this.originX = this.x;
                this.originY = this.y;
                times = 0;
            }
            
            this.x = this.originX + level * (Math.random() > 0.5 ? 1 : -1);
            this.y = this.originY + level * (Math.random() > 0.5 ? 1 : -1);

            times++;
            if(times > 10){
                this.x = this.originX;
                this.y = this.originY;
                return;
            }

            Laya.timer.once(10, this, this.shake, [level, times]);
        }

        actions (data) {
            // for(let i in data){
                this.buildings[data.id].action(data.act, data.a);
            // }
        }

        events (data) {
            if(data.e == "shake"){
                this.shake(data.level);
                return;
            }
            // for(let i in data){
                this.buildings[data.id].event(data.a);
            // }
        }

        reset () {
            // for(let i in this.roles){
            //     delete this.roles[i];
            // }
            // for(let i in this.bullets){
            //     delete this.bullets[i];
            // }
            for(let f in this.floors){
                this.floors[f].recover();
            }
            for(let b in this.buildings){
                this.buildings[b].recover();
            }
            this.floors.length;
            this.buildings.length;
        }
    }

    Sail.class(TileMap, "Com.Room.Map.Base");
}